#include "PlayerMenu.h"
#include "StringUtilities.h"
#include "Utilities.h"
#include "PrintUtilities.h"
#include "MenuManager.h"
#include "ServiceProvider.h"
#include "GamePrintUtils.h"
#include "TeamManager.h"
#include "Team.h"
#include "LeagueManager.h"
#include "MatchData.h"
#include "UserManager.h"
#include "People.h"
#include "ShortListNotificationMenu.h"
#include "UserSelectionMenu.h"
#include "OfferTeamMenu.h"
#include "OfferPlayerMenu.h"
#include "ConfirmPanel.h"
#include "NotificationPanel.h"

PlayerMenu::PlayerMenu(MenuManager* const i_menuManager)
	:Menu(i_menuManager)
	,m_player(0)
{
}


PlayerMenu::~PlayerMenu(void)
{
}

void PlayerMenu::OnEnter()
{
	m_waitState = NONE;
	m_playerTeam = GetSP()->GetTeamMgr().GetTeam(m_player->GetTeamID());
	const size_t numUsers = GetSP()->GetUserMgr().GetUserList().size();
	const bool sp = (numUsers == 1);
	const bool mp = (numUsers > 1);
	m_canHandle = (m_playerTeam && m_playerTeam->IsUserControlled());
	m_canBuy = (mp || (sp && !m_canHandle));
	m_notAIMatch = (numUsers != 0);
}

void PlayerMenu::Draw() const
{
	using STD::cout;
	using STD::endl;

	cout << Print::Title("PLAYER STATISTICS:");

	ShowPlayer();

	STL::string options;

	if(m_notAIMatch)
	{
		options += "55) Add/Remove from Shortlist\n";
	}

	options += "66) View Player Palmares (TODO: not yet implemented)\n";

	if(m_canHandle)
	{
		options += "77) Renew contract\n";
		options += "88) Sell Player\n";
	}

	if(m_canBuy)
	{
		options += "99) Make an Offer to ";
		if(m_player->GetTeamID() == Utilities::INVALID_ID)
			options += m_player->GetName();
		else
			options += GetTeamName(*m_player, GetSP()->GetTeamMgr().GetTeamName(m_player->GetTeamID())) + " (TODO: not yet implemented!)";
		options += "\n";
	}

	options += "\n 0) Return to previous menu'.";

	cout << Print::Options(options) << "Selection: ";
}

bool PlayerMenu::Input(const STL::string& i_input)
{
	bool goodInput = true;
	const int res = Utilities::StringToInt(i_input);

	switch(res)
	{
	case 55:
		if(m_notAIMatch)
		{
			UserSelectionMenu* usMenu = static_cast<UserSelectionMenu*>(GetMM()->GetUserSelectionMenu());
			STL::string sentence("Who is going to Add/Remove ");
			sentence += m_player->GetName();
			sentence += " to his shortlist?";
			usMenu->SetSentence(sentence);

			ShortListNotificationMenu* slnMenu = static_cast<ShortListNotificationMenu*>(GetMM()->GetShortListNotificationMenu());
			slnMenu->m_player = m_player;
			usMenu->SetNextMenu(slnMenu);
			GetMM()->PushMenu(usMenu);
		}
		break;

	case 66:
		break;

	case 77:
#ifndef DARIO
		if(m_canHandle)
		{
			OfferPlayerMenu* opMenu = static_cast<OfferPlayerMenu*>(GetMM()->GetOfferPlayerMenu());
			opMenu->SetPlayer(m_player);
			opMenu->SetUserTeam(m_playerTeam);
			GetMM()->PushMenu(opMenu);
		}
#endif
		break;

	case 88:
		if(m_canHandle)
		{
			m_waitState = CANTSELL;
			NotificationPanel* notificationPanel = static_cast<NotificationPanel*>(GetMM()->GetNotificationPanel());
			if(m_player->IsPlayer() && (m_playerTeam->GetNumPlayers() <= Team::GetParams().MIN_TEAM_PLAYERS))
			{
				notificationPanel->SetDelegate(this);
				notificationPanel->SetSentence("You can't sell the player, your team has reached minimum players number!\n");
				GetMM()->PushMenu(notificationPanel);
			}
			if(m_player->IsTrainer() && (m_playerTeam->GetNumTrainers() <= Team::GetParams().MIN_TEAM_TRAINERS))
			{
				notificationPanel->SetDelegate(this);
				notificationPanel->SetSentence("You can't sell the trainer, your team has reached minimum trainers number!\n");
				GetMM()->PushMenu(notificationPanel);
			}
			else
			{
				m_waitState = SELLING;
				ConfirmPanel* confirmPanel = static_cast<ConfirmPanel*>(GetMM()->GetConfirmPanel());
				confirmPanel->SetDelegate(this);
				confirmPanel->SetSentence("Do you really want to Sell " + m_player->GetName() + " ?");
				GetMM()->PushMenu(confirmPanel);
			}
		}
		break;

	case 99:
		if(m_canBuy)
		{
			UserSelectionMenu* usMenu = static_cast<UserSelectionMenu*>(GetMM()->GetUserSelectionMenu());
			STL::string sentence("Who is going to make an offer to ");
			const bool isBusy = m_player->GetTeamID() != Utilities::INVALID_ID;
			if(isBusy)
			{
				sentence += GetTeamName(*m_player, GetSP()->GetTeamMgr().GetTeamName(m_player->GetTeamID()));
				sentence += " in order to buy ";
			}
			sentence += m_player->GetName();
			sentence += "?";
			usMenu->SetSentence(sentence);

			OfferTeamMenu* otMenu = static_cast<OfferTeamMenu*>(GetMM()->GetOfferTeamMenu());
			otMenu->SetPlayer(m_player);

			OfferPlayerMenu* opMenu = static_cast<OfferPlayerMenu*>(GetMM()->GetOfferPlayerMenu());
			opMenu->SetPlayer(m_player);

			usMenu->SetNextMenu(isBusy ? GetMM()->GetOfferTeamMenu() : GetMM()->GetOfferPlayerMenu());
			GetMM()->PushMenu(usMenu);
		}
		break;

	case 0:
		GetMM()->PopMenu();
		break;
	};

	return goodInput;
}


void PlayerMenu::ShowPlayer() const
{
	static const char* s_cards[] = {"   ", "Y  ", "YY ", " R ", "YR ", "RR "};

	using namespace STD;
	using namespace Print;
	using namespace Utilities;

	const int tabNum = People::GetParams().MAX_CHAR_NAME + 5;
	const int maxTeamNameSize = Team::GetParams().MAX_CHAR_TEAM_NAME;
	const int SkillTab = 10;

	const PeopleHistory& hist = m_player->GetHistory();
	const PeopleSkills& skills = m_player->GetSkills();

	cout << "GENERAL STATS" << endl;
	cout << endl;

	cout << TabUpTo("Name: ", tabNum);
	cout << m_player->GetName() << endl;

	cout << TabUpTo("Age: ", tabNum);
	cout << hist.GetAge() << endl;

	cout << TabUpTo("Birth Year:", tabNum);
	cout << hist.GetBirthYear() << endl;

	cout << TabUpTo("Starting Year:", tabNum);
	cout << hist.GetStartingYear() << endl;

	cout << TabUpTo("Number Seasons as Player:", tabNum);
	if(hist.GetNumSeason(StatusPlayer) == 0)
		cout << "---" << endl;
	else
		cout << hist.GetNumSeason(StatusPlayer) << endl;

	cout << TabUpTo("Player Retirement Year:", tabNum);
	if(hist.GetNumSeason(StatusPlayer) == 0 || hist.GetRetirementYear(StatusPlayer) < 0)
		cout << "---" << endl;
	else
		cout << hist.GetRetirementYear(StatusPlayer) << endl;

	cout << TabUpTo("Player Retirement Age:", tabNum);
	if(hist.GetNumSeason(StatusPlayer) == 0 || hist.GetRetirementYear(StatusPlayer) < 0)
		cout << "---" << endl;
	else
		cout << hist.GetRetirementAge(StatusPlayer) << endl;

	cout << TabUpTo("Number Seasons as Trainer:", tabNum);
	if(hist.GetNumSeason(StatusTrainer) == 0)
		cout << "---" << endl;
	else
		cout << hist.GetNumSeason(StatusTrainer) << endl;

	cout << TabUpTo("Trainer Retirement Year:", tabNum);
	if(hist.GetNumSeason(StatusTrainer) == 0 || hist.GetRetirementYear(StatusTrainer) < 0)
		cout << "---" << endl;
	else
		cout << hist.GetRetirementYear(StatusTrainer) << endl;

	cout << TabUpTo("Trainer Retirement Age:", tabNum);
	if(hist.GetNumSeason(StatusTrainer) == 0 || hist.GetRetirementYear(StatusTrainer) < 0)
		cout << "---" << endl;
	else
		cout << hist.GetRetirementAge(StatusTrainer) << endl;

	cout << endl;
	cout << "PLAYER SKILLS" << endl;
	cout << endl;

	cout << TabUpTo("Goalkeeping: ", tabNum);
	cout << TabUpTo(skills.m_playerSkills[Goalkeeper], SkillTab) << "Max: " << skills.m_maxPlayerSkills[Goalkeeper] << endl;

	cout << TabUpTo("Defense: ", tabNum);
	cout << TabUpTo(skills.m_playerSkills[Defender], SkillTab) << "Max: " << skills.m_maxPlayerSkills[Defender] << endl;

	cout << TabUpTo("Attack: ", tabNum);
	cout << TabUpTo(skills.m_playerSkills[Attacker], SkillTab) << "Max: " << skills.m_maxPlayerSkills[Attacker] << endl;

	cout << endl;
	cout << "TRAINER SKILLS" << endl;
	cout << endl;

	cout << TabUpTo("Goalkeeping: ", tabNum);
	cout << skills.m_trainerSkills[Goalkeeper] << endl;

	cout << TabUpTo("Defense: ", tabNum);
	cout << skills.m_trainerSkills[Defender] << endl;

	cout << TabUpTo("Attack: ", tabNum);
	cout << skills.m_trainerSkills[Attacker] << endl;

	cout << endl;
	cout << "PHYSICS SKILLS" << endl;
	cout << endl;

	cout << TabUpTo("Resistance: ", tabNum);
	cout << skills.m_physicsSkills[Resistance] << endl;

	cout << TabUpTo("Fatigue: ", tabNum);
	cout << skills.m_physicsSkills[Fatigue] << endl;

	cout << TabUpTo("Stamina: ", tabNum);
	cout << skills.m_physicsSkills[Stamina] << endl;

	cout << endl;
	cout << "MENTAL SKILLS" << endl;
	cout << endl;

	cout << TabUpTo("Charisma: ", tabNum);
	cout << skills.m_mentalSkills[Charisma] << endl;

	cout << TabUpTo("Intelligence: ", tabNum);
	cout << skills.m_mentalSkills[Intelligence] << endl;

	cout << TabUpTo("Aggressivity: ", tabNum);
	cout << skills.m_mentalSkills[Aggressivity] << endl;

	// current situation

	cout << endl;
	cout << "CURRENT SITUATION" << endl;
	cout << endl;

	cout << TabUpTo("Activity Status", tabNum);
	if(hist.GetRetirementYear(StatusPlayer) >= 0) 
	{
		if(hist.GetRetirementYear(StatusTrainer) >= 0) 
		{
			if(hist.GetStartingYear() ==  hist.GetRetirementYear(StatusPlayer)) 
				cout << "Former Trainer. Now Retired" << endl;
			else if(hist.GetRetirementYear(StatusTrainer) ==  hist.GetRetirementYear(StatusPlayer)) 
				cout << "Former Player. Now Retired" << endl;
			else
				cout << "Former Player and Trainer. Now Retired" << endl;
		}else{
			if(hist.GetStartingYear() == hist.GetRetirementYear(StatusPlayer)) 
				cout << "Active Trainer" << endl;
			else
				cout << "Former Player. Active Trainer" << endl;
		}
	}else{
		cout << "Active Player. Retiring Percent: " << m_player->GetRetirePercent() << "%" << endl;
	}

	cout << TabUpTo("Team: ", tabNum);
	cout << (m_player->IsRetired() ? "Retired" : GetTeamName(*m_player, GetSP()->GetTeamMgr().GetTeamName(m_player->GetTeamID()))) << endl;

	cout << TabUpTo("Salary: ", tabNum);
	cout << (m_player->IsRetired() ? "Retired" : IntToString(m_player->GetSalary())) << endl;

#ifndef DARIO
	cout << TabUpTo("Duration of the contract: ", tabNum);
	cout << (m_player->IsRetired() ? "Retired" : IntToString(m_player->GetContract()->m_years)) << endl;
#else
	cout << TabUpTo("Buy Value: ", tabNum);
	cout << (m_player->IsRetired() ? "Retired" : IntToString(m_player->BuyValue())) << endl;

	cout << TabUpTo("Sell Value: ", tabNum);
	cout << (m_player->IsRetired() ? "Retired" : IntToString(m_player->SellValue())) << endl;
#endif

	cout << endl;

	// Player History

	const size_t maxSize = hist.GetNumHistoryEntry();
	bool wasPlayer = false;
	size_t i=0;
	for(i=0; i<maxSize; ++i)
	{
		if(hist.GetStatus(hist.GetRecord(i).m_numSeason) != StatusPlayer)
			break;

		if(!wasPlayer)
		{
			wasPlayer = true;

			cout << "PLAYER HISTORY" << endl;
			cout << endl;

			cout << TabUpTo("Years", 6);
			cout << TabUpTo("Team", maxTeamNameSize+1);
			cout << TabUpTo("Matc", 5);
			cout << TabUpTo("Eval", 5);
			cout << TabUpTo("MoM", 4);
			cout << TabUpTo("Goal", 5);
			cout << TabUpTo("Ratio", 6);
			cout << TabUpTo("Inj", 4);
			cout << TabUpTo("InjD", 5);
			cout << TabUpTo("Yel", 4);
			cout << TabUpTo("Red", 4);
			cout << endl;
		}

		cout << TabUpTo(hist.GetRecord(i).m_numSeason, 6);
		cout << TabUpTo(GetSP()->GetTeamMgr().GetTeamName(hist.GetRecord(i).m_teamID), maxTeamNameSize+1);
		cout << TabUpTo(hist.GetRecord(i).m_matchPlayed, 5);
		cout << TabUpTo(hist.GetRecord(i).GetEvalStr(), 5);
		cout << TabUpTo(hist.GetRecord(i).m_manOfTheMatch, 4);
		cout << TabUpTo(hist.GetRecord(i).m_goalScored, 5);
		cout << TabUpTo(RatioToString(hist.GetRecord(i).GetRatio()), 6);
		cout << TabUpTo(hist.GetRecord(i).m_numOfInjury, 4);
		cout << TabUpTo(hist.GetRecord(i).m_numOfInjuryDays,5);
		cout << TabUpTo(hist.GetRecord(i).m_yellowCard, 4);
		cout << TabUpTo(hist.GetRecord(i).m_redCard, 4);
		cout << endl;
	}
	if(wasPlayer)
	{
		cout << endl;
		cout << TabUpTo("Total", 6 + maxTeamNameSize+1);
		cout << TabUpTo(hist.GetTotalMatch(StatusPlayer), 5);
		cout << TabUpTo(hist.GetTotalEvalStr(), 5);
		cout << TabUpTo(hist.GetTotalMoM(), 4);
		cout << TabUpTo(hist.GetTotalScoredGoal(), 5);
		cout << TabUpTo(RatioToString(hist.GetTotalScoredGoalRatio()), 6);
		cout << TabUpTo(hist.GetTotalNumOfInjury(), 4);
		cout << TabUpTo(hist.GetTotalNumOfInjuryDays(), 5);
		cout << TabUpTo(hist.GetTotalYellowCard(), 4);
		cout << TabUpTo(hist.GetTotalRedCard(), 4);
		cout << endl << endl;
	}

	// Trainer History

	bool wasTrainer = false;
	for(size_t j=i; j<maxSize; ++j)
	{
		if(hist.GetStatus(hist.GetRecord(j).m_numSeason) != StatusTrainer)
			break;

		if(!wasTrainer)
		{
			wasTrainer = true;

			cout << "TRAINER HISTORY" << endl;
			cout << endl;

			cout << TabUpTo("Years", 6);
			cout << TabUpTo("Team", maxTeamNameSize+1);
			cout << TabUpTo("Matc", 5);
			cout << TabUpTo("Wins", 5);
			cout << TabUpTo("Draw", 5);
			cout << TabUpTo("Loss", 5);
			cout << endl;
		}

		cout << TabUpTo(hist.GetRecord(j).m_numSeason, 6);
		cout << TabUpTo(GetSP()->GetTeamMgr().GetTeamName(hist.GetRecord(j).m_teamID), maxTeamNameSize+1);
		cout << TabUpTo(hist.GetRecord(j).m_matchPlayed, 5);
		cout << TabUpTo("TODO", 5);
		cout << TabUpTo("TODO", 5);
		cout << TabUpTo("TODO", 5);
		cout << endl;
	}
	if(wasTrainer)
	{
		cout << endl;
		cout << TabUpTo("Total", 6 + maxTeamNameSize+1);
		cout << TabUpTo(hist.GetTotalMatch(StatusTrainer), 5);
		cout << TabUpTo("TODO", 5);
		cout << TabUpTo("TODO", 5);
		cout << TabUpTo("TODO", 5);
		cout << endl << endl;
	}

	// aggregates
	if(wasPlayer && wasTrainer)
	{
		cout << TabUpTo("Total Matches", 6 + maxTeamNameSize+1);
		cout << TabUpTo(hist.GetTotalMatch(StatusPlayerOrTrainer), 5);
		cout << endl << endl;
	}

	// Current Season

	if(m_player->IsPlayer() && m_player->GetTeamID() != INVALID_ID)
	{
		MatchDataVec matches;
		GetSP()->GetLeagueMgr().GetTeamMatches(m_player->GetTeamID(), matches);

		if(!matches.empty())
		{
			cout << endl;
			cout << "CURRENT SEASON" << endl;
			cout << endl;
			cout << "NUM EVAL M GL YR " << endl;

			int matchCount = 0;
			for (size_t i=0; i<matches.size(); ++i)
			{
				const MatchPlayerData* const pData = matches[i]->GetPlayerData(m_player->GetId());
				cout << TabUpTo(++matchCount, 4);
				if(pData)
				{
					cout << EvalToStr(pData->m_evaluation);
					cout << (matches[i]->IsPlayerMOM(m_player->GetId()) ? " * " : "   ");
					cout << (pData->m_goals== 0 ? "   " : TabUpTo(pData->m_goals, 3));
					cout << s_cards[STL::min(5, pData->m_cards)];
				}
				else
				{
					cout << "----         "; 
				}
				cout << "     ";
				PrintMatchResult(cout, *matches[i], GetSP(), false);
				cout << endl;
			}
		}
		cout << endl;
	}
}

void PlayerMenu::PanelWillClose(bool result)
{
	switch(m_waitState)
	{
	case CANTSELL:
		break;

	case SELLING:
		if(result)
		{
			m_playerTeam->SellPlayer(m_player);
		}
		break;
	};
}